package org.broadinstitute.hellbender.tools.copynumber.formats.collections;

import org.broadinstitute.hellbender.exceptions.UserException;
import org.broadinstitute.hellbender.tools.copynumber.gcnv.GermlineCNVNamingConstants;
import org.broadinstitute.hellbender.tools.copynumber.gcnv.IntegerCopyNumberState;
import org.broadinstitute.hellbender.utils.tsv.DataLine;
import org.broadinstitute.hellbender.utils.tsv.TableColumnCollection;

import java.io.File;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * Collection of baseline copy-number states.
 *
 * @author Mehrtash Babadi &lt;mehrtash@broadinstitute.org&gt;
 */
public final class BaselineCopyNumberCollection extends AbstractSampleRecordCollection<IntegerCopyNumberState> {

    public BaselineCopyNumberCollection(final File inputFile) {
        super(inputFile,
                new TableColumnCollection(GermlineCNVNamingConstants.BASELINE_COPY_NUMBER_TABLE_COLUMN),
                getBaselineCopyNumberRecordFromDataLineDecoder(inputFile),
                getBaselineCopyNumberRecordToDataLineEncoder());
    }

    /**
     * Generates an instance of {@link IntegerCopyNumberState} from a {@link DataLine} entry read from
     * a baseline copy-number file generated by `gcnvkernel`.
     */
    private static Function<DataLine, IntegerCopyNumberState> getBaselineCopyNumberRecordFromDataLineDecoder(final File inputFile) {
        return dataLine -> {
            try {
                return new IntegerCopyNumberState(dataLine.getInt(GermlineCNVNamingConstants.BASELINE_COPY_NUMBER_TABLE_COLUMN));
            } catch (final IllegalArgumentException ex) {
                throw new UserException.BadInput(
                        String.format("Error parsing baseline copy-number file (%s) at line %d.",
                                inputFile.getAbsolutePath(), dataLine.getLineNumber()));
            }
        };
    }

    /**
     * Generates an instance of {@link DataLine} from {@link IntegerCopyNumberState} for writing baseline
     * copy-number collection to a file.
     */
    private static BiConsumer<IntegerCopyNumberState, DataLine> getBaselineCopyNumberRecordToDataLineEncoder() {
        return (baselineCopyNumberState, dataLine) -> dataLine.append(baselineCopyNumberState.getCopyNumber());
    }
}
